package com.jic.veteran.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.EscapeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jic.veteran.common.service.RedisService;
import com.jic.veteran.dao.UmsAdminRoleRelationDao;
import com.jic.veteran.dto.ProjectDto;
import com.jic.veteran.dto.RecentDonateDto;
import com.jic.veteran.mapper.PayInfoMapper;
import com.jic.veteran.mapper.ProjectBasicMapper;
import com.jic.veteran.mapper.UmsAdminRoleRelationMapper;
import com.jic.veteran.model.*;
import com.jic.veteran.service.UmsAdminCacheService;
import com.jic.veteran.service.UmsAdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 后台用户缓存操作Service实现类
 * Created by macro on 2020/3/13.
 */
@Slf4j
@Service
public class UmsAdminCacheServiceImpl implements UmsAdminCacheService {
    @Autowired
    private UmsAdminService adminService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private UmsAdminRoleRelationMapper adminRoleRelationMapper;
    @Autowired
    private UmsAdminRoleRelationDao adminRoleRelationDao;
    @Autowired
    private PayInfoMapper payInfoMapper;
    @Autowired
    private ProjectBasicMapper projectBasicMapper;
    @Value("${redis.database}")
    private String REDIS_DATABASE;
    @Value("${redis.expire.common}")
    private Long REDIS_EXPIRE;
    @Value("${redis.key.admin}")
    private String REDIS_KEY_ADMIN;
    @Value("${redis.key.resourceList}")
    private String REDIS_KEY_RESOURCE_LIST;
    @Value("${redis.key.projectId}")
    private String REDIS_KEY_PROJECT_ID;
    @Value("${redis.key.projectList}")
    private String REDIS_KEY_PROJECT_LIST;
    @Value("${redis.key.donationList}")
    private String REDIS_KEY_PROJECT_DONATE_LIST;
    @Value("${redis.key.member}")
    private String REDIS_KEY_MEMBER;
    @Value("${redis.key.payBasicInfo}")
    private String REDIS_KEY_PAY_BASIC_INFO;
    @Value("${redis.key.cmsArticleList}")
    private String REDIS_KEY_CMS_ARTICLE_LIST;
    @Value("${redis.key.bigScreenTime}")
    private String REDIS_KEY_BIG_SCREEN_TIME;

    @Override
    public void delAdmin(Long adminId) {
        UmsAdmin admin = adminService.getItem(adminId);
        if (admin != null) {
            String key = REDIS_DATABASE + ":" + REDIS_KEY_ADMIN + ":" + admin.getUsername();
            redisService.del(key);
        }
    }

    @Override
    public void delResourceList(Long adminId) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_RESOURCE_LIST + ":" + adminId;
        redisService.del(key);
    }

    @Override
    public void delResourceListByRole(Long roleId) {
        UmsAdminRoleRelationExample example = new UmsAdminRoleRelationExample();
        example.createCriteria().andRoleIdEqualTo(roleId);
        List<UmsAdminRoleRelation> relationList = adminRoleRelationMapper.selectByExample(example);
        if (CollUtil.isNotEmpty(relationList)) {
            String keyPrefix = REDIS_DATABASE + ":" + REDIS_KEY_RESOURCE_LIST + ":";
            List<String> keys = relationList.stream().map(relation -> keyPrefix + relation.getAdminId()).collect(Collectors.toList());
            redisService.del(keys);
        }
    }

    @Override
    public void delResourceListByRoleIds(List<Long> roleIds) {
        UmsAdminRoleRelationExample example = new UmsAdminRoleRelationExample();
        example.createCriteria().andRoleIdIn(roleIds);
        List<UmsAdminRoleRelation> relationList = adminRoleRelationMapper.selectByExample(example);
        if (CollUtil.isNotEmpty(relationList)) {
            String keyPrefix = REDIS_DATABASE + ":" + REDIS_KEY_RESOURCE_LIST + ":";
            List<String> keys = relationList.stream().map(relation -> keyPrefix + relation.getAdminId()).collect(Collectors.toList());
            redisService.del(keys);
        }
    }

    @Override
    public void delResourceListByResource(Long resourceId) {
        List<Long> adminIdList = adminRoleRelationDao.getAdminIdList(resourceId);
        if (CollUtil.isNotEmpty(adminIdList)) {
            String keyPrefix = REDIS_DATABASE + ":" + REDIS_KEY_RESOURCE_LIST + ":";
            List<String> keys = adminIdList.stream().map(adminId -> keyPrefix + adminId).collect(Collectors.toList());
            redisService.del(keys);
        }
    }

    @Override
    public UmsAdmin getAdmin(String username) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_ADMIN + ":" + username;
        return (UmsAdmin) redisService.get(key);
    }

    @Override
    public void setAdmin(UmsAdmin admin) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_ADMIN + ":" + admin.getUsername();
        redisService.set(key, admin, REDIS_EXPIRE);
    }

    @Override
    public List<UmsResource> getResourceList(Long adminId) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_RESOURCE_LIST + ":" + adminId;
        return (List<UmsResource>) redisService.get(key);
    }

    @Override
    public void setResourceList(Long adminId, List<UmsResource> resourceList) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_RESOURCE_LIST + ":" + adminId;
        redisService.set(key, resourceList, REDIS_EXPIRE);
    }

    @Override
    public void setProject(ProjectDto projectDto) {
        String keyId = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_ID + ":" + projectDto.getProjectBasic().getId();
        String keyProjectId = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_ID + ":" + projectDto.getProjectBasic().getProjectId();
        JSONObject jsonObject = JSONUtil.parseObj(projectDto);
        jsonObject.setDateFormat("yyyy-MM-dd HH:mm:ss");
        redisService.set(keyId, JSONUtil.toJsonStr(jsonObject));
        redisService.set(keyProjectId, JSONUtil.toJsonStr(jsonObject));
    }

    @Override
    public void delProject(ProjectBasic projectBasic) {
        if(ObjectUtil.isNotEmpty(projectBasic)) {
            String keyId = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_ID + ":" + projectBasic.getId();
            String keyProjectId = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_ID + ":" + projectBasic.getProjectId();
            redisService.del(keyId);
            redisService.del(keyProjectId);
        }
    }

    @Override
    public void setProjectDtoList(ProjectBasic projectBasic) {
        String key = REDIS_DATABASE+ ":" + REDIS_KEY_PROJECT_LIST;
        JSONObject jsonObject = JSONUtil.parseObj(projectBasic,JSONConfig.create().setOrder(true).setDateFormat("yyyy-MM-dd HH:mm:ss"));
        String value = jsonObject.toString();
        log.info("project list value : {}",value);
        if(!redisService.sIsMember(key,value)) {
            redisService.sAdd(key,value);
        }
    }

    @Override
    public void removeProjectFromList(ProjectBasic projectBasic) {
        String key = REDIS_DATABASE+ ":" + REDIS_KEY_PROJECT_LIST;
        JSONObject jsonObject = JSONUtil.parseObj(projectBasic, JSONConfig.create().setOrder(true).setDateFormat("yyyy-MM-dd HH:mm:ss"));
        String value = jsonObject.toString();
        log.info("project list value : {}",value);
        if(redisService.sIsMember(key,value)) {
            redisService.sRemove(key,value);
        }
    }

    @Override
    public void lPushLimit(ProjectDonationDetail projectDonationDetail) {
        if (null != projectDonationDetail) {
            RecentDonateDto recentDonateDto = new RecentDonateDto();
            recentDonateDto.setProjectId(projectDonationDetail.getProjectId());
            recentDonateDto.setProjectName(projectDonationDetail.getProjectName());
            recentDonateDto.setFinishTime(projectDonationDetail.getDonationTime());
            recentDonateDto.setNickName(projectDonationDetail.getUserName());
            UmsMember umsMember = getMember(projectDonationDetail.getUserId());
            if (null!=umsMember) {
                recentDonateDto.setAvatarUrl(umsMember.getAvatarUrl());
            }
            recentDonateDto.setOpenid(projectDonationDetail.getUserId());
            recentDonateDto.setTrxamt(projectDonationDetail.getDonationAmount());
            String key = REDIS_DATABASE+ ":" + REDIS_KEY_PROJECT_DONATE_LIST + ":" +projectDonationDetail.getProjectId();
            redisService.lPush(key,recentDonateDto);
            redisService.lTrim(key,0,4);
        }
    }

    @Override
    public PayInfo getPayInfo() {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PAY_BASIC_INFO;
        String value = (String) redisService.get(key);
        if(StrUtil.isNotEmpty(value)) {
            return JSONUtil.toBean(value,PayInfo.class);
        }
        PayInfo payInfo = payInfoMapper.getPayInfoStatus();
        redisService.set(key,JSONUtil.toJsonStr(payInfo));
        return payInfo;
    }

    @Override
    public void setPayInfo(PayInfo payInfo) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PAY_BASIC_INFO;
        redisService.set(key,JSONUtil.toJsonStr(payInfo));
    }

    private UmsMember getMember(String username) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_MEMBER + ":" + username;
        return (UmsMember) redisService.get(key);
    }

    @Override
    public void setCmsArticleInfoList(CmsArticleInfo cmsArticleInfo) {
        String key = REDIS_DATABASE+ ":" + REDIS_KEY_CMS_ARTICLE_LIST + ":" + cmsArticleInfo.getArticleType();
        JSONObject jsonObject = JSONUtil.parseObj(cmsArticleInfo,JSONConfig.create().setOrder(true).setDateFormat("yyyy-MM-dd HH:mm:ss"));
        String value = jsonObject.toString();
        log.info("cmsArticleInfo list value : {}",value);
        if(!redisService.sIsMember(key,value)) {
            redisService.sAdd(key,value);
        }
    }

    @Override
    public void removeCmsArticleInfoFromList(CmsArticleInfo cmsArticleInfo) {
        String key = REDIS_DATABASE+ ":" + REDIS_KEY_CMS_ARTICLE_LIST + ":" + cmsArticleInfo.getArticleType();
        redisService.sMembers(key).stream().map(
                member -> {
                    log.info("clear cmsArticleInfo cache value {}",member);
                    CmsArticleInfo cmsArticleInfoCache = JSONUtil.toBean((String) member, CmsArticleInfo.class);
                    log.info("cmsArticleInfo cache id : {},cmsArticleInfo db id {}",cmsArticleInfoCache.getId(),cmsArticleInfo.getId());
                    if (cmsArticleInfoCache.getId().equals(cmsArticleInfo.getId())) {
                        redisService.sRemove(key,member);
                    }
                    return cmsArticleInfoCache;
                }
        ).collect(Collectors.toList());
        /*JSONObject jsonObject = JSONUtil.parseObj(cmsArticleInfo, JSONConfig.create().setOrder(true).setDateFormat("yyyy-MM-dd HH:mm:ss"));
        String value = jsonObject.toString();
        log.info("cmsArticleInfo list value : {}",value);
        if(redisService.sIsMember(key,value)) {
            redisService.sRemove(key,value);
        }*/
    }

    @Override
    public void setBigScreenTime(String bigScreenTime) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_BIG_SCREEN_TIME;
        redisService.set(key,bigScreenTime);
    }

    @Override
    public void removeBigScreenTime() {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_BIG_SCREEN_TIME;
        redisService.del(key);
    }
}
